package me.flyray.bsin.server.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import me.flyray.bsin.domain.constants.WalletConstants;
import me.flyray.bsin.domain.entity.ChainCoin;
import me.flyray.bsin.domain.entity.Wallet;
import me.flyray.bsin.domain.entity.WalletAccount;
import me.flyray.bsin.blockchain.enums.WalletType;
import me.flyray.bsin.domain.request.WalletAccountDTO;
import me.flyray.bsin.domain.response.WalletAccountVO;
import me.flyray.bsin.exception.BusinessException;
import me.flyray.bsin.facade.service.WalletAccountService;
import me.flyray.bsin.infrastructure.biz.WalletAccountBiz;
import me.flyray.bsin.infrastructure.mapper.ChainCoinMapper;
import me.flyray.bsin.infrastructure.mapper.WalletAccountMapper;
import me.flyray.bsin.infrastructure.mapper.WalletMapper;
import me.flyray.bsin.infrastructure.utils.QrCodeUtils;
import me.flyray.bsin.mybatis.utils.Pagination;
import me.flyray.bsin.security.contex.LoginInfoContextHelper;
import me.flyray.bsin.security.domain.LoginUser;
import me.flyray.bsin.validate.QueryGroup;
import org.springframework.validation.annotation.Validated;
import org.apache.shenyu.client.apache.dubbo.annotation.ShenyuDubboService;
import org.apache.shenyu.client.apidocs.annotations.ApiDoc;
import org.apache.shenyu.client.apidocs.annotations.ApiModule;
import org.apache.shenyu.client.dubbo.common.annotation.ShenyuDubboClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @author Admin
* @description 针对表【crm_wallet_account(钱包账户;)】的数据库操作Service实现
* @createDate 2024-04-24 20:35:43
*/
@Slf4j
@ApiModule(value = "walletAccount")
@ShenyuDubboService("/walletAccount")
public class WalletAccountServiceImpl implements WalletAccountService {

    @Autowired
    private WalletAccountMapper walletAccountMapper;
    @Autowired
    private ChainCoinMapper chainCoinMapper;
    @Autowired
    private WalletMapper walletMapper;
    @Autowired
    private WalletAccountBiz walletAccountBiz;

    @Override
    @ShenyuDubboClient("/add")
    @ApiDoc(desc = "add")
    @Transactional(rollbackFor = Exception.class)
    public void add(WalletAccountDTO walletAccountDTO) {
        log.info("请求WalletAccountService.addWalletAccount,参数:{}", walletAccountDTO);
        try{
            String chainCoinId = walletAccountDTO.getChainCoinNo();
            ChainCoin chainCoin = chainCoinMapper.selectById(chainCoinId);
            String privateKey = walletAccountDTO.getPrivateKey();
            String pubKey = walletAccountDTO.getPublicKey();
            String address = walletAccountDTO.getAddress();
            String walletNo = walletAccountDTO.getWalletNo();
            if(chainCoin == null || WalletConstants.COIN_STATUS_DISABLED.equals(chainCoin.getStatus())) {
                throw new BusinessException("CHAIN_COIN_NOT_EXISTS_OR_OFF_SHELVES");
            }
            // 导入钱包
            walletAccountBiz.addWalletAccount(walletNo, chainCoinId, privateKey, pubKey, address);
            log.info("添加钱包账户成功，钱包编号: {}, 币种: {}", walletNo, chainCoinId);
        }catch (BusinessException be){
            throw be;
        }catch (Exception e){
            log.error("添加钱包账户失败，钱包编号: {}, 币种: {}, 错误: {}", 
                walletAccountDTO.getWalletNo(), walletAccountDTO.getChainCoinNo(), e.getMessage(), e);
            throw new BusinessException("SYSTEM_ERROR");
        }
    }


    @Override
    @ShenyuDubboClient("/create")
    @ApiDoc(desc = "create")
    @Transactional(rollbackFor = Exception.class)
    public void create(WalletAccountDTO walletAccountDTO) {
        log.info("请求WalletAccountService.createWalletAccount,参数:{}", walletAccountDTO);
        try{
            String chainCoinId = walletAccountDTO.getChainCoinNo();
            String walletNo = walletAccountDTO.getWalletNo();
            ChainCoin chainCoin = chainCoinMapper.selectById(chainCoinId);
            if(chainCoin == null || WalletConstants.COIN_STATUS_DISABLED.equals(chainCoin.getStatus())) {
                throw new BusinessException("CHAIN_COIN_NOT_EXISTS_OR_OFF_SHELVES");
            }
            Wallet wallet = walletMapper.selectById(walletNo);
            if (wallet == null) {
                throw new BusinessException("WALLET_NOT_EXISTS");
            }
            // 创建钱包账户
            walletAccountBiz.createWalletAccount(wallet, chainCoin);
            log.info("创建钱包账户成功，钱包编号: {}, 币种: {}", walletNo, chainCoinId);
        }catch (BusinessException be){
            throw be;
        }catch (Exception e){
            log.error("创建钱包账户失败，钱包编号: {}, 币种: {}, 错误: {}", 
                walletAccountDTO.getWalletNo(), walletAccountDTO.getChainCoinNo(), e.getMessage(), e);
            throw new BusinessException("SYSTEM_ERROR");
        }
    }

    @Override
    @ShenyuDubboClient("/updateStatus")
    @ApiDoc(desc = "updateStatus")
    public void updateAccountStatus(WalletAccount params) {
        log.info("请求WalletAccountService.updateAccountStatus,参数:{}", params);
        try{
            WalletAccount walletAccount = new WalletAccount();
            walletAccount.setSerialNo(params.getSerialNo());
            walletAccount.setStatus(params.getStatus());
            walletAccountMapper.updateById(walletAccount);
            log.info("更新账户状态成功，账户编号: {}, 状态: {}", params.getSerialNo(), params.getStatus());
        }catch (BusinessException be){
            throw be;
        }catch (Exception e){
            log.error("更新账户状态失败，账户编号: {}, 错误: {}", 
                params.getSerialNo(), e.getMessage(), e);
            throw new BusinessException("SYSTEM_ERROR");
        }
    }

    @Override
    @ShenyuDubboClient("/getPageList")
    @ApiDoc(desc = "getPageList")
    public Page<WalletAccountVO> getPageList(@Validated(QueryGroup.class) WalletAccountDTO walletAccountDTO) {
        log.info("请求WalletAccountService.pageList,参数:{}", walletAccountDTO);
        LoginUser loginUser = LoginInfoContextHelper.getLoginUser();
        Pagination pagination = walletAccountDTO.getPagination();
        walletAccountDTO.setTenantId(loginUser.getTenantId());
        return walletAccountMapper.pageList(new Page<>(pagination.getPageNum(), pagination.getPageSize()), walletAccountDTO);
    }

    /**
     * 查询用户的钱包账户
     * @param walletAccountDTO
     * @return
     */
    @ShenyuDubboClient("/getList")
    @ApiDoc(desc = "getList")
    @Override
    public List<WalletAccountVO> getList(WalletAccountDTO walletAccountDTO) {
        LoginUser loginUser = LoginInfoContextHelper.getLoginUser();
        // 查询用户默认钱包
        LambdaQueryWrapper<Wallet> walletLambdaQueryWrapper = new LambdaQueryWrapper<>();
        walletLambdaQueryWrapper.eq(Wallet::getTenantId, loginUser.getTenantId());
        walletLambdaQueryWrapper.eq(Wallet::getBizRoleTypeNo, loginUser.getBizRoleTypeNo());
        walletLambdaQueryWrapper.eq(Wallet::getType, WalletType.DEFAULT.getCode());
        Wallet wallet = walletMapper.selectOne(walletLambdaQueryWrapper);
        if (wallet == null) {
            throw new BusinessException("WALLET_NOT_EXISTS");
        }
        // 根据钱包编号查询钱包账户
        List<WalletAccountVO> walletAccounts = walletAccountMapper.selectListByWalletNo(loginUser.getTenantId(), wallet.getSerialNo());
        return walletAccounts;
    }

    @Override
    @ShenyuDubboClient("/getDetail")
    @ApiDoc(desc = "getDetail")
    public WalletAccountVO getDetail(WalletAccountDTO walletAccountDTO) {
        log.info("请求WalletAccountService.getDetail,参数:{}", walletAccountDTO);
        try{
            return walletAccountMapper.selectBySerialNo(walletAccountDTO.getSerialNo());
        }catch (BusinessException be){
            throw be;
        }catch (Exception e){
            log.error("查询账户详情失败，账户编号: {}, 错误: {}", 
                walletAccountDTO.getSerialNo(), e.getMessage(), e);
            throw new BusinessException("SYSTEM_ERROR");
        }
    }

    @Override
    @ShenyuDubboClient("/edit")
    @ApiDoc(desc = "edit")
    @Transactional(rollbackFor = Exception.class)
    public void edit(WalletAccountDTO walletAccountDTO) {
        log.info("请求WalletAccountService.edit,参数:{}", walletAccountDTO);
        LoginUser loginUser = LoginInfoContextHelper.getLoginUser();
        try{
            WalletAccount walletAccount = new WalletAccount();
            BeanUtils.copyProperties(walletAccountDTO, walletAccount);
            
            WalletAccount oldAccount = walletAccountMapper.selectById(walletAccount.getSerialNo());
            if(oldAccount == null) {
                throw new BusinessException("WALLET_ACCOUNT_NOT_EXISTS");
            }
            
            walletAccount.setUpdateBy(loginUser.getUserId());
            walletAccount.setUpdateTime(new Date());
            walletAccountMapper.updateById(walletAccount);
            log.info("编辑账户成功，账户编号: {}", walletAccountDTO.getSerialNo());
        }catch (BusinessException be){
            throw be;
        }catch (Exception e){
            log.error("编辑账户失败，账户编号: {}, 错误: {}", 
                walletAccountDTO.getSerialNo(), e.getMessage(), e);
            throw new BusinessException("SYSTEM_ERROR");
        }
    }

    @Override
    @ShenyuDubboClient("/delete")
    @ApiDoc(desc = "delete")
    @Transactional(rollbackFor = Exception.class)
    public void delete(WalletAccountDTO walletAccountDTO) {
        log.info("请求WalletAccountService.delete,参数:{}", walletAccountDTO);
        LoginUser loginUser = LoginInfoContextHelper.getLoginUser();
        try{
            WalletAccount walletAccount = walletAccountMapper.selectById(walletAccountDTO.getSerialNo());
            if(walletAccount == null) {
                throw new BusinessException("WALLET_ACCOUNT_NOT_EXISTS");
            }
            walletAccount.setUpdateBy(loginUser.getUserId());
            walletAccount.setUpdateTime(new Date());
            walletAccount.setDelFlag(WalletConstants.DEL_FLAG_DELETED);
            walletAccountMapper.updateById(walletAccount);
            log.info("删除账户成功，账户编号: {}", walletAccountDTO.getSerialNo());
        }catch (BusinessException be){
            throw be;
        }catch (Exception e){
            log.error("删除账户失败，账户编号: {}, 错误: {}", 
                walletAccountDTO.getSerialNo(), e.getMessage(), e);
            throw new BusinessException("SYSTEM_ERROR");
        }
    }


    @Override
    @ShenyuDubboClient("/getAddressQrCode")
    @ApiDoc(desc = "getAddressQrCode")
    public Map<String, Object> getAddressQrCode(String serialNo) {
        log.debug("请求WalletAccountService.getAddressQrCode,参数:{}", serialNo);
        Map<String,Object> map = new HashMap<>();
        try{
            WalletAccountVO walletAccountVO = walletAccountMapper.selectBySerialNo(serialNo);
            String base64Pic = QrCodeUtils.creatRrCode(walletAccountVO.getAddress(), 200,200);
            map.put("qrCode",base64Pic);
            map.put("coin",walletAccountVO.getCoin());
            map.put("chainIdentifier",walletAccountVO.getChainIdentifier());
            map.put("address",walletAccountVO.getAddress());
            return map;
        }catch (BusinessException be){
            throw be;
        }catch (Exception e){
            log.error("获取地址二维码失败，账户编号: {}, 错误: {}", 
                serialNo, e.getMessage(), e);
            throw new BusinessException("SYSTEM_ERROR");
        }
    }

}




